home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / packages / lazy-lock.el < prev    next >
Encoding:
Text File  |  1995-08-30  |  41.4 KB  |  914 lines

  1. ;;; lazy-lock.el --- Lazy demand-driven fontification for fast Font Lock mode.
  2.  
  3. ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
  6. ;; Keywords: faces files
  7. ;; Version: 1.12
  8.  
  9. ;; LCD Archive Entry:
  10. ;; lazy-lock|Simon Marshall|simon@gnu.ai.mit.edu|
  11. ;; Lazy Font Lock mode (with fast demand-driven fontification).|
  12. ;; 13-Jul-1995|1.12|~/modes/lazy-lock.el.gz|
  13.  
  14. ;; The archive is archive.cis.ohio-state.edu in /pub/gnu/emacs/elisp-archive.
  15.  
  16. ;;; This file is part of GNU Emacs.
  17.  
  18. ;; GNU Emacs is free software; you can redistribute it and/or modify
  19. ;; it under the terms of the GNU General Public License as published by
  20. ;; the Free Software Foundation; either version 2, or (at your option)
  21. ;; any later version.
  22.  
  23. ;; GNU Emacs is distributed in the hope that it will be useful,
  24. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26. ;; GNU General Public License for more details.
  27.  
  28. ;; You should have received a copy of the GNU General Public License
  29. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  30. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  
  32. ;;; Commentary:
  33.  
  34. ;; Purpose:
  35. ;;
  36. ;; To make visiting buffers in `font-lock-mode' faster by making fontification
  37. ;; be demand-driven and stealthy.
  38. ;; Fontification only occurs when, and where, necessary.
  39. ;;
  40. ;; See caveats and feedback below.  See also the defer-lock and fast-lock
  41. ;; packages.  (But don't use lazy-lock.el and fast-lock.el at the same time!)
  42.  
  43. ;; Installation:
  44. ;; 
  45. ;; Put this file somewhere where Emacs can find it (i.e., in one of the paths
  46. ;; in your `load-path'), `byte-compile-file' it, and put in your ~/.emacs:
  47. ;;
  48. ;; (autoload 'turn-on-lazy-lock "lazy-lock"
  49. ;;   "Unconditionally turn on Lazy Lock mode.")
  50. ;;
  51. ;; (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
  52. ;;
  53. ;; Start up a new Emacs and use font-lock as usual (except that you can use the
  54. ;; so-called "gaudier" fontification regexps on big files without frustration).
  55. ;;
  56. ;; In a buffer (which has `font-lock-mode' enabled) which is at least
  57. ;; `lazy-lock-minimum-size' characters long, only the visible portion of the
  58. ;; buffer will be fontified.  Motion around the buffer will fontify those
  59. ;; visible portions that were not previous fontified.  If the variable
  60. ;; `lazy-lock-hide-invisible' is non-nil, redisplay will be delayed until after
  61. ;; fontification.  Otherwise, text that has not yet been fontified is displayed
  62. ;; in `lazy-lock-invisible-foreground'.
  63. ;;
  64. ;; If stealth fontification is enabled, fontification will occur in invisible
  65. ;; parts of the buffer after `lazy-lock-stealth-time' seconds of idle time.
  66.  
  67. ;; Advanced Use:
  68. ;;
  69. ;; You can also do fancy things with `advice'.  For example, to fontify when
  70. ;; dragging the scroll-bar in Emacs, you could put in your ~/.emacs:
  71. ;;
  72. ;; (autoload 'lazy-lock-post-command-fontify-windows "lazy-lock")
  73. ;;
  74. ;; (defadvice scroll-bar-drag-1 (after fontify-window activate compile)
  75. ;;   (let ((lazy-lock-walk-windows nil) (lazy-lock-hide-invisible nil))
  76. ;;     (lazy-lock-post-command-fontify-windows)))
  77. ;;
  78. ;; Or to fontify when the Debugger pops up a source code window:
  79. ;;
  80. ;; (autoload 'lazy-lock-fontify-walk-windows "lazy-lock")
  81. ;;
  82. ;; (defadvice gud-display-line (after fontify-window activate compile)
  83. ;;   (let ((lazy-lock-walk-windows t) (lazy-lock-hide-invisible t))
  84. ;;     (lazy-lock-fontify-walk-windows)))
  85. ;;
  86. ;; Scott Byer <byer@mv.us.adobe.com> suggested this to fontify the visible part
  87. ;; of an insertion only:
  88. ;;
  89. ;; (defvar lazy-lock-insert-commands
  90. ;;   "A list of insertion commands." 
  91. ;;   '(yank yank-pop clipboard-yank hilit-yank hilit-yank-pop 
  92. ;;     mail-yank-original mouse-yank-at-click mouse-yank-secondary
  93. ;;     yank-rectangle))
  94. ;;
  95. ;; (defadvice font-lock-after-change-function (around fontify-insertion
  96. ;;                                             activate compile)
  97. ;;   (if (or (not (memq this-command lazy-lock-insert-commands))
  98. ;;       (and (pos-visible-in-window-p beg) (pos-visible-in-window-p end)))
  99. ;;       ad-do-it
  100. ;;     (let ((this-command 'ignore))
  101. ;;       (put-text-property beg end 'fontified nil)
  102. ;;       (lazy-lock-fontify-window))))
  103. ;;
  104. ;; Let me know if you use any other `advice' and I'll put it here.  Thanks.
  105. ;;
  106. ;; These kinds of things with `advice' aren't done automatically because they
  107. ;; cause large packages (advice.el plus bytecomp.el and friends) to be loaded.
  108.  
  109. ;; Caveats:
  110. ;;
  111. ;; Lazy Lock mode does not work efficiently with Outline mode.  This is because
  112. ;; when in Outline mode, although text may be hidden (not visible in the
  113. ;; window), the text is visible to Emacs Lisp code (not surprisingly) and Lazy
  114. ;; Lock fontifies it mercilessly.  Hopefully this will be fixed one day.
  115. ;;
  116. ;; Lazy Lock mode does not fontify windows as they appear:
  117. ;;
  118. ;; 1.  With `query-replace' or `ispell-*', as Lazy Lock only knows about point
  119. ;; motion after the command exits.
  120. ;;
  121. ;; 2.  When displayed by gud.el (the Grand Unified Debugger), as they are
  122. ;; displayed via a process sentinel.  See `Advanced Use' above.
  123. ;;
  124. ;; 3.  In XEmacs 19.12, when the last command was invoked via a mouse event,
  125. ;; because of a bug/feature in/of `sit-for'.
  126. ;;
  127. ;; 4.  In other random situations that I don't know about (yet).
  128. ;;
  129. ;; If you have `lazy-lock-hide-invisible' you may notice that redisplay occurs
  130. ;; before fontification regardlessly.  This is due to other packages sitting on
  131. ;; `post-command-hook' and provoking redisplay.  If you use these packages, you
  132. ;; can't use `lazy-lock-hide-invisible'.
  133. ;;
  134. ;; If you have `lazy-lock-hide-invisible' and use scrollbar scrolling using
  135. ;; Emacs 19, hidden text will not be fontified as it becomes visible.  It is
  136. ;; expected that Emacs 19 will provide the necessary hooks in future, to solve
  137. ;; this problem and the problem above.
  138. ;;
  139. ;; Unless otherwise stated, "Emacs 19.X" means versions up to and including X.
  140. ;;
  141. ;; In Emacs 19.25, one `window-start'/`window-end' bug means that if you open a
  142. ;; file in another frame (such as via `find-tag-other-frame'), the whole buffer
  143. ;; is fontified regardless.  Upgrade!
  144. ;;
  145. ;; In Emacs 19.25, fontification by stealth is turned off because of a fatal
  146. ;; bug in `previous-single-property-change'.  Upgrade!
  147. ;;
  148. ;; In Emacs 19.28, if you see a message in the minibuffer of the form
  149. ;;  "Fontifying window... done.  (Restarted in foo.c)"
  150. ;; it means the Garbage Collector has marked some (subsequently used) text
  151. ;; properties.  Lazy Lock attempts to recover the situation by restarting in
  152. ;; that buffer.  Unfortunately, that buffer will be left in a writable and
  153. ;; modified state.  Also, other windows may not be fontified when this happens.
  154. ;; To reduce the frequency of this bug occuring, increase in your ~/.emacs the
  155. ;; value of `gc-cons-threshold' to, say, 1Meg, e.g.:
  156. ;;
  157. ;; (setq gc-cons-threshold (* 1024 1024))
  158. ;;
  159. ;; The solution is to upgrade!  (With thanks to Kevin Broadey for help here.)
  160. ;;
  161. ;; For XEmacs 19.11 and Lucid Emacs 19.10 users, lazy-lock sort-of works.
  162. ;; There are bugs in text property and point/window primatives.  Upgrade!
  163.  
  164. ;; Feedback:
  165. ;;
  166. ;; Feedback is welcome.
  167. ;; To submit a bug report (or make comments) please use the mechanism provided:
  168. ;;
  169. ;; M-x lazy-lock-submit-bug-report RET
  170.  
  171. ;; History:
  172. ;;
  173. ;; 0.01--1.00:
  174. ;; - Changed name from fore-lock to lazy-lock.  Shame though.
  175. ;; - Dropped `advice'-wrapping completely.  Ask me if you're interested in it.
  176. ;; - Made `lazy-lock-mode' ignore `post-command-hook' and `buffer-file-name'.
  177. ;; - Made `lazy-lock-fontify-window' check `lazy-lock-mode' and `this-command'.
  178. ;; - Made `lazy-lock-fontify-window' redisplay via `sit-for'.
  179. ;; - Added `lazy-lock-minimum-size' to control `lazy-lock-mode'.
  180. ;; 1.00--1.01:
  181. ;; - Added `lazy-lock-fontify-buffer'.
  182. ;; - Made `lazy-lock-fontify-window' ignore `lazy-lock-mode'.
  183. ;; - Made `lazy-lock-fontify-window' suspicious of `window-' favourites again.
  184. ;; - Added `lazy-lock-delay-commands' (idea from William G. Dubuque).
  185. ;; - Added `lazy-lock-ignore-commands' for completeness.
  186. ;; - Added `lazy-lock-continuity-time' for normal input delay.
  187. ;; 1.01--1.02:
  188. ;; - Made `lazy-lock-fontify-window' cope with multiple unfontified regions.
  189. ;; - Made `lazy-lock-mode' remove `fontified' properties if turned off.
  190. ;; - Made `lazy-lock-fontify-window' fontify by lines.
  191. ;; - Added `lazy-lock-cache-position' buffer local to detect visibility change.
  192. ;; - Added `lazy-lock-post-command-hook' to do the waiting.
  193. ;; - Made `lazy-lock-fontify-window' just do the fontification.
  194. ;; - Made `lazy-lock-mode' append `lazy-lock-post-command-hook'.
  195. ;; - Added `lazy-lock-walk-windows' to hack multi-window motion.
  196. ;; - Made `lazy-lock-post-command-hook' `walk-windows' if variable is non-nil.
  197. ;; - Removed `lazy-lock-ignore-commands' since insertion may change window.
  198. ;; - Added `lazy-lock-fontify-stealthily' and `lazy-lock-stealth-time'.
  199. ;; - Made `lazy-lock-post-command-hook' use them.
  200. ;; 1.02--1.03:
  201. ;; - Made `lazy-lock-fontify-stealthily' do `forward-line' not `previous-line'.
  202. ;; - Made `lazy-lock-fontify-stealthily' `move-to-window-line' first.
  203. ;; - Made `lazy-lock-fontify-stealthily' use `text-property-any' for region.
  204. ;; - Made `lazy-lock-post-command-hook' loop on `lazy-lock-fontify-stealthily'.
  205. ;; 1.03--1.04:
  206. ;; - Made `lazy-lock-mode' reset `lazy-lock-cache-position'.
  207. ;; - Made `lazy-lock-post-command-hook' `widen' for `if' `text-property-any'.
  208. ;; - Made `lazy-lock-fontify-stealthily' return `text-property-any'.
  209. ;; - Added `lazy-lock-percent-fontified' for a/be-musement.
  210. ;; - Made `lazy-lock-post-command-hook' use it.
  211. ;; - Made `lazy-lock-mode' use `make-local-hook' etc. if available.
  212. ;; - Made `lazy-lock-mode' use `before-revert-hook' and `after-revert-hook'.
  213. ;; - Made `lazy-lock-post-command-hook' protect `deactivate-mark'.
  214. ;; - Adds `lazy-lock-post-command-hook' globally to `post-command-hook'.
  215. ;; 1.04--1.05:
  216. ;; - Made `lazy-lock-mode' test `make-local-hook' not `emacs-minor-version'.
  217. ;; 1.05--1.06:
  218. ;; - Added `lazy-lock-ignore-commands' for commands that leave no event but do.
  219. ;; - Made `lazy-lock-post-command-hook' check `lazy-lock-ignore-commands'.
  220. ;; 1.06--1.07:
  221. ;; - Removed `before-revert-hook' and `after-revert-hook' use.
  222. ;; 1.07--1.08:
  223. ;; - Added `lazy-lock-submit-bug-report'.
  224. ;; - Made `lazy-lock-post-command-hook' check `executing-macro'.
  225. ;; - Made it sort-of/almost work for XEmacs (help from Jonas Jarnestrom).
  226. ;; - XEmacs: Fix `text-property-not-all' (fix based on fast-lock.el 3.05 fix).
  227. ;; - XEmacs: Set `font-lock-no-comments' and alias `frame-parameters'.
  228. ;; - Made `byte-compile-warnings' omit `unresolved' on compilation.
  229. ;; - Made `lazy-lock-post-command-hook' protect `buffer-undo-list'.
  230. ;; - Moved `deactivate-mark' and `buffer-undo-list' protection to functions.
  231. ;; - Added `lazy-lock-invisible-foreground' (idea from Boris Goldowsky).
  232. ;; - XEmacs: Fix to use `text-property-not-all' t, not `text-property-any' nil.
  233. ;; - Made `lazy-lock-percent-fontified' return `round' to an integer.
  234. ;; - XEmacs: Fix `text-property-any' (fix and work around for a bug elsewhere).
  235. ;; - XEmacs: Fix `lazy-lock-submit-bug-report' for reporter.el & vm-window.el.
  236. ;; - XEmacs: Made `lazy-lock-fontify-window' loop `while' `<' not `/='.
  237. ;; - Use `font-lock-after-change-function' to do the fontification.
  238. ;; 1.08--1.09:
  239. ;; - Made `lazy-lock-post-command-hook' protect with `condition-case'.
  240. ;; - Made `lazy-lock-cache-start' to cache `window-start'.
  241. ;; - Made `lazy-lock-fontify-window' check and cache `lazy-lock-cache-start'.
  242. ;; - Renamed `lazy-lock-cache-position' to `lazy-lock-cache-end'.
  243. ;; - XEmacs: Fix for `font-lock-after-change-function'.
  244. ;; - Adds `lazy-lock-post-command-hook' globally to `window-setup-hook'.
  245. ;; 1.09--1.10:
  246. ;; - Made `buffer-file-name' be `let' to prevent supersession (Kevin Broadey).
  247. ;; - Made `lazy-lock-submit-bug-report' `require' reporter (Ilya Zakharevich).
  248. ;; - Made `lazy-lock-mode' and `turn-on-lazy-lock' succeed `autoload' cookies.
  249. ;; - Added `lazy-lock-fontify-walk-windows' for walking window fontification.
  250. ;; - Added `lazy-lock-fontify-walk-stealthily' for walking stealth.
  251. ;; - Removed `move-to-window-line' from `lazy-lock-fontify-stealthily'.
  252. ;; - Made `lazy-lock-percent-fontified' use `truncate' rather than `round'.
  253. ;; - Added other `*-argument' to `lazy-lock-ignore-commands' (Kevin Broadey).
  254. ;; - Made `lazy-lock-fontify-stealthily' not assume buffer is part `fontified'.
  255. ;; - Emacs: Fix for `font-lock-fontify-region'.
  256. ;; - Made `lazy-lock-post-command-hook' check for minibuffer (Kevin Broadey).
  257. ;; - Added `lazy-lock-stealth-nice' for niceness during stealth fontification.
  258. ;; - Added `lazy-lock-stealth-lines' for chunks of stealth fontification.
  259. ;; 1.10--1.11: incorporated hack by Ben Wing from William Dubuque's fontifly.el
  260. ;; - Made `lazy-lock-fontify-stealthily' see a non `fontified' preceding line.
  261. ;; - XEmacs: Fix `text-property-any' and `text-property-not-all' (Ben Wing).
  262. ;; - XEmacs: Fix `lazy-lock-continuity-time' (Ben Wing).
  263. ;; - Added awful `lazy-lock-running-xemacs-p' (Ben Wing).
  264. ;; - Made loading set `emacs-minor-version' if it's not bound.
  265. ;; - Added `lazy-lock-hide-invisible' to control redisplay.
  266. ;; - Made `lazy-lock-post-command-hook' use it in `sit-for' (Ben Wing).
  267. ;; - Made `lazy-lock-fontify-window' move relative to `end-of-line' if non-nil.
  268. ;; - Added `lazy-lock-fontify-region' so packages can ensure fontification.
  269. ;; - Made `lazy-lock-fontify-walk-stealthily' do stealth widening.
  270. ;; - Made `lazy-lock-fontify-stealthily' always do adjacent preceding regions.
  271. ;; - Added `lazy-lock-after-fontify-buffer'.
  272. ;; - XEmacs: Removed `font-lock-no-comments' incompatibility code.
  273. ;; - Removed `lazy-lock-delay-time' and `lazy-lock-delay-commands'.
  274. ;; - Removed `lazy-lock-post-command' and split the functionality.
  275. ;; - Adds `lazy-lock-post-command-fontify-windows' on first.
  276. ;; - Adds `lazy-lock-post-command-fontify-stealthily' on last.
  277. ;; - Made `lazy-lock-mode' ensure both first and last on `post-command-hook'.
  278. ;; - Made `lazy-lock-mode' ensure `font-lock-mode' is on.
  279. ;; - Wrap `lazy-lock-post-command-fontify-stealthily' for errors (David Karr).
  280. ;; - Added `calcDigit-key' to `lazy-lock-ignore-commands' (Bob Glickstein).
  281. ;; - Wrap `lazy-lock-running-xemacs-p' with `eval-and-compile' (Erik Naggum).
  282. ;; - XEmacs: Fix use of `previous-single-property-change' (Jim Thompson).
  283. ;; - XEmacs: Fix `next-single-property-change' fix for 19.11 (Jim Thompson).
  284. ;; - Added `lazy-lock-post-resize-fontify-windows' to fontify on resizing.
  285. ;; - Adds globally to `window-size-change-functions'.
  286. ;; - Added `lazy-lock-post-setup-fontify-windows' to fontify after start up.
  287. ;; - Adds globally to `window-setup-hook'.
  288. ;; - Made `lazy-lock-post-command-fontify-windows' check for `input-pending-p'.
  289. ;; - Made `save-selected-window' to restore the `selected-window'.
  290. ;; - Use `save-selected-window' rather than `save-window-excursion'.
  291. ;; 1.11--1.12:
  292. ;; - Made `lazy-lock-post-command-fontify-windows' do `set-buffer' first.
  293. ;; - Made `lazy-lock-fontify-stealthily' respect narrowing before point.
  294. ;; - Added `lazy-lock-post-setup-ediff-control-frame' for Ediff control frame.
  295. ;; - Adds globally to `ediff-after-setup-control-frame-hooks'.
  296. ;; - Wrap `save-selected-window' with `save-excursion' for `current-buffer'.
  297.  
  298. (require 'font-lock)
  299.  
  300. (eval-when-compile
  301.   ;; Only `require' so `ediff-multiframe-setup-p' is expanded at compile time.
  302.   (condition-case nil (require 'ediff) (file-error))
  303.   ;; Well, shouldn't Lazy Lock be as lazy as possible?
  304.   ;(setq byte-compile-dynamic t byte-compile-dynamic-docstrings t)
  305.   ;; Shut Emacs' byte-compiler up (cf. stop me getting mail from users).
  306.   (setq byte-compile-warnings '(free-vars callargs redefine)))
  307.  
  308. (defun lazy-lock-submit-bug-report ()
  309.   "Submit via mail a bug report on lazy-lock.el."
  310.   (interactive)
  311.   (require 'reporter)
  312.   (let ((reporter-prompt-for-summary-p t))
  313.     (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "lazy-lock 1.12"
  314.      '(lazy-lock-walk-windows lazy-lock-continuity-time
  315.        lazy-lock-stealth-time lazy-lock-stealth-nice lazy-lock-stealth-lines
  316.        lazy-lock-hide-invisible lazy-lock-invisible-foreground
  317.        lazy-lock-minimum-size lazy-lock-ignore-commands)
  318.      nil nil
  319.      (concat "Hi Si.,
  320.  
  321. I want to report a bug.  I've read the `Bugs' section of `Info' on Emacs, so I
  322. know how to make a clear and unambiguous report.  To reproduce the bug:
  323.  
  324. Start a fresh Emacs via `" invocation-name " -no-init-file -no-site-file'.
  325. In the `*scratch*' buffer, evaluate:"))))
  326.  
  327. ;; Let's define `emacs-minor-version' if no-one else has.
  328. (if (not (boundp 'emacs-minor-version))
  329.     (eval-and-compile
  330.       (defconst emacs-minor-version
  331.     (save-match-data
  332.       (string-match "^[0-9]+\\.\\([0-9]+\\)" emacs-version)
  333.       (string-to-int
  334.        (substring emacs-version (match-beginning 1) (match-end 1)))))))
  335.  
  336. ;; Yuck, but we make so much use of this variable it's probably worth it.
  337. (eval-and-compile
  338.   (defconst lazy-lock-running-xemacs-p
  339.     (not (null (save-match-data (string-match "Lucid" emacs-version))))))
  340.  
  341. (defvar lazy-lock-cache-start nil)    ; for window fontifiction
  342. (defvar lazy-lock-cache-end nil)    ; for window fontifiction
  343. (defvar lazy-lock-cache-continue nil)    ; for stealth fontifiction
  344. (defvar lazy-lock-mode nil)        ; for modeline
  345.  
  346. ;; User Variables:
  347.  
  348. (defvar lazy-lock-minimum-size (* 25 1024)
  349.   "*If non-nil, the minimum size for buffers.
  350. Only buffers more than this can have demand-driven fontification.
  351. If nil, means size is irrelevant.")
  352.  
  353. (defvar lazy-lock-walk-windows t
  354.   "*If non-nil, fontify windows other than the selected window.
  355. If `all-frames', fontify windows even on other frames.
  356. A non-nil value slows down redisplay.")
  357.  
  358. ;; XEmacs exercises a bug in the Xt event loop.
  359. (defvar lazy-lock-continuity-time
  360.   (if lazy-lock-running-xemacs-p (if (featurep 'lisp-float-type) 0.001 1) 0)
  361.   "*Time in seconds to delay before normal window fontification.
  362. Window fontification occurs if there is no input within this time.")
  363.  
  364. ;; `previous-single-property-change' at `point-min' up to Emacs 19.25 is fatal.
  365. ;; `text-property-any', `text-property-not-all' and
  366. ;; `next-single-property-change' up to XEmacs 19.11 are too broke.
  367. (defvar lazy-lock-stealth-time
  368.   (if (> emacs-minor-version (if lazy-lock-running-xemacs-p 11 25)) 30)
  369.   "*Time in seconds to delay before beginning stealth fontification.
  370. Stealth fontification occurs if there is no input within this time.
  371. If nil, means no fontification by stealth.")
  372.  
  373. (defvar lazy-lock-stealth-lines
  374.   (if lazy-lock-running-xemacs-p 250 (if (> emacs-minor-version 29) 250 100))
  375.   "*If non-nil, the maximum size of a chunk of stealth fontification.
  376. Each iteration of stealth fontification can fontify this number of lines.
  377. If nil, means use `window-height' for the maximum chunk size.")
  378.  
  379. (defvar lazy-lock-stealth-nice (if (featurep 'lisp-float-type) 0.125 1)
  380.   "*Time in seconds to pause during chunks of stealth fontification.
  381. The higher the value, the lower the load made by Emacs on the machine, but the
  382. longer the stealth fontification takes.")
  383.  
  384. (defvar lazy-lock-ignore-commands
  385.   (append
  386.    ;; Standard commands...
  387.    '(universal-argument digit-argument negative-argument
  388.      isearch-other-control-char isearch-other-meta-char)
  389.    ;; And some resulting from non-standard packages...
  390.    (if (fboundp 'calc) '(calcDigit-key)))
  391.   "A list of commands after which fontification should not occur.
  392. To speed up typing response, at the cost of Lazy Lock not fontifying when
  393. insertion causes scrolling, you could add `self-insert-command' to this list.")
  394.  
  395. (defvar lazy-lock-hide-invisible lazy-lock-running-xemacs-p
  396.   "*If non-nil, hide invisible text while it is fontified.
  397. If non-nil, redisplay is delayed until after fontification occurs.  If nil,
  398. text is shown (in `lazy-lock-invisible-foreground') while it is fontified.
  399. A non-nil value slows down redisplay.")
  400.  
  401. (defvar lazy-lock-invisible-foreground
  402.   (cond ((fboundp 'x-color-defined-p)
  403.      (if (x-color-defined-p "gray50") "gray50"))
  404.     ((fboundp 'valid-color-name-p)
  405.      (if (valid-color-name-p "gray50") "gray50"))
  406.     ((fboundp 'x-valid-color-name-p)
  407.      (if (x-valid-color-name-p "gray50") "gray50")))
  408.   "The foreground colour to use to display invisible text.
  409. If nil, the default foreground is used.  If t, the default background is used.
  410. If a string, it should be a colour to use (either its name or its RGB value).
  411. Invisible text is momentarily seen (if `lazy-lock-hide-invisible' is nil) when
  412. scrolling into unfontified regions.")
  413.  
  414. ;; User Functions:
  415.  
  416. ;;;###autoload
  417. (defun lazy-lock-mode (&optional arg)
  418.   "Toggle Lazy Lock mode.
  419. With arg, turn Lazy Lock mode on if and only if arg is positive and the buffer
  420. is at least `lazy-lock-minimum-size' characters long.
  421.  
  422. When Lazy Lock mode is enabled, fontification is demand-driven and stealthy:
  423.  
  424.  - Fontification occurs in visible parts of buffers when necessary.
  425.    Occurs if there is no input after pausing for `lazy-lock-continuity-time'.
  426.  
  427.  - Fontification occurs in invisible parts when Emacs has been idle.
  428.    Occurs if there is no input after pausing for `lazy-lock-stealth-time'.
  429.  
  430. If `lazy-lock-hide-invisible' is non-nil, text is not displayed until it is
  431. fontified, otherwise it is displayed in `lazy-lock-invisible-foreground'.
  432.  
  433. See also variables `lazy-lock-walk-windows', `lazy-lock-stealth-lines',
  434. `lazy-lock-stealth-nice' and `lazy-lock-ignore-commands'.
  435.  
  436. Use \\[lazy-lock-submit-bug-report] to send bug reports or feedback."
  437.   (interactive "P")
  438.   (set (make-local-variable 'lazy-lock-mode)
  439.        (and (<= (or lazy-lock-minimum-size 0) (buffer-size))
  440.         (if arg (> (prefix-numeric-value arg) 0) (not lazy-lock-mode))))
  441.   (if (and lazy-lock-mode (not font-lock-mode))
  442.       ;; Turned on `lazy-lock-mode' rather than using `font-lock-mode-hook'.
  443.       (progn
  444.     (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
  445.     (font-lock-mode 1))
  446.     ;; Make sure that we're in the correct positions to avoid hassle.
  447.     (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-windows)
  448.     (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily)
  449.     (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-windows)
  450.     (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily t)
  451.     ;; Let's get down to business.
  452.     (if (not lazy-lock-mode)
  453.     (let ((modified (buffer-modified-p)) (inhibit-read-only t)
  454.           (buffer-undo-list t) deactivate-mark buffer-file-name)
  455.       (remove-text-properties (point-min) (point-max) '(fontified nil))
  456.       (or modified (set-buffer-modified-p nil)))
  457.       (if (and (not lazy-lock-hide-invisible) lazy-lock-invisible-foreground)
  458.       (lazy-lock-colour-invisible))
  459.       (set (make-local-variable 'lazy-lock-cache-start) 0)
  460.       (set (make-local-variable 'lazy-lock-cache-end) 0)
  461.       (set (make-local-variable 'font-lock-fontified) t))))
  462.  
  463. ;;;###autoload
  464. (defun turn-on-lazy-lock ()
  465.   "Unconditionally turn on Lazy Lock mode."
  466.   (lazy-lock-mode 1))
  467.  
  468. (if (< emacs-minor-version (if lazy-lock-running-xemacs-p 12 29))
  469.     ;; We don't need this in Emacs 19.29 or XEmacs 19.12.
  470.     (defun lazy-lock-fontify-buffer ()
  471.       "Fontify the current buffer where necessary."
  472.       (interactive)
  473.       (lazy-lock-fontify-region (point-min) (point-max))))
  474.  
  475. ;; API Functions:
  476.  
  477. (defun lazy-lock-fontify-region (start end &optional buffer)
  478.   "Fontify between START and END in BUFFER where necessary."
  479.   (save-excursion
  480.     (and buffer (set-buffer buffer))
  481.     (save-restriction
  482.       (narrow-to-region start end)
  483.       (let ((lazy-lock-stealth-lines (count-lines start end)))
  484.     (while (text-property-not-all start end 'fontified t)
  485.       (lazy-lock-fontify-stealthily))))))
  486.  
  487. (defun lazy-lock-after-fontify-buffer ()
  488.   ;; Mark the buffer as `fontified'.
  489.   (let ((modified (buffer-modified-p)) (inhibit-read-only t)
  490.     (buffer-undo-list t) deactivate-mark buffer-file-name)
  491.     (put-text-property (point-min) (point-max) 'fontified t)
  492.     (or modified (set-buffer-modified-p nil))))
  493.  
  494. ;; Just a cleaner-looking way of coping with Emacs' and XEmacs' `sit-for'.
  495. (defmacro lazy-lock-sit-for (seconds &optional nodisp)
  496.   (if lazy-lock-running-xemacs-p
  497.       (` (sit-for (, seconds) (, nodisp)))
  498.     (` (sit-for (, seconds) 0 (, nodisp)))))
  499.  
  500. ;; Using `save-window-excursion' provokes `window-size-change-functions'.
  501. ;; I prefer `save-walking-excursion', of course, because I have a warped mind.
  502. (if (fboundp 'save-selected-window)
  503.     nil
  504.   (eval-and-compile
  505.     (defmacro save-selected-window (&rest body)
  506.       "Execute the BODY forms, restoring the selected window.
  507. Does not restore the value of point in the selected window, or anything else."
  508.       (` (let ((original-window (selected-window)))
  509.        (unwind-protect
  510.            (progn (,@ body))
  511.          (select-window original-window))))))
  512.   (put 'save-selected-window 'lisp-indent-function 0))
  513.  
  514. ;; Functions for hooks:
  515.  
  516. (defun lazy-lock-post-command-fontify-windows ()
  517.   ;; We might not be where we think we are, since `post-command-hook' is run
  518.   ;; before `command_loop_1' makes sure we have the correct buffer selected.
  519.   (set-buffer (window-buffer))
  520.   ;; Do groovy things if (a) not in a macro, (b) no input pending, (c) got a
  521.   ;; real command, (d) not in the minibuffer, and (e) no input after waiting
  522.   ;; for `lazy-lock-continuity-time'.
  523.   (if (or executing-kbd-macro
  524.       (input-pending-p)
  525.       (memq this-command lazy-lock-ignore-commands)
  526.       (window-minibuffer-p (selected-window)))
  527.       (setq lazy-lock-cache-continue nil)
  528.     (setq lazy-lock-cache-continue t)
  529.     (if (lazy-lock-sit-for lazy-lock-continuity-time lazy-lock-hide-invisible)
  530.     ;; Do the visible parts of the buffer(s), i.e., the window(s).
  531.     (if (or (not lazy-lock-walk-windows)
  532.         (and (eq lazy-lock-walk-windows t) (one-window-p t)))
  533.         (if lazy-lock-mode (condition-case nil (lazy-lock-fontify-window)))
  534.       (lazy-lock-fontify-walk-windows)))))
  535.  
  536. (defun lazy-lock-post-command-fontify-stealthily ()
  537.   ;; Do groovy things if (a-d) above, (e) not moving the mouse, and (f) no
  538.   ;; input after after waiting for `lazy-lock-stealth-time'.
  539.   (if (and lazy-lock-cache-continue lazy-lock-stealth-time)
  540.       (condition-case data
  541.       (if (lazy-lock-sit-for lazy-lock-stealth-time)
  542.           ;; Do the invisible parts of buffers.
  543.           (lazy-lock-fontify-walk-stealthily)) 
  544.     (error (message "Fontifying stealthily... %s" data)))))
  545.  
  546. (defun lazy-lock-post-resize-fontify-windows (frame)
  547.   ;; Fontify all windows in FRAME.
  548.   (let ((lazy-lock-walk-windows t) executing-kbd-macro this-command)
  549.     (save-excursion
  550.       (save-selected-window
  551.     (select-frame frame)
  552.     (lazy-lock-post-command-fontify-windows)))))
  553.  
  554. (defun lazy-lock-post-setup-emacs-fontify-windows ()
  555.   ;; Fontify all windows in all frames.
  556.   (let ((lazy-lock-walk-windows 'all-frames) executing-kbd-macro this-command)
  557.     (lazy-lock-post-command-fontify-windows)))
  558.  
  559. (defun lazy-lock-post-setup-ediff-control-frame ()
  560.   ;; Fontify all windows in all frames when using the Ediff control frame.
  561.   (make-local-variable 'lazy-lock-walk-windows)
  562.   (setq lazy-lock-walk-windows (if (ediff-multiframe-setup-p) 'all-frames t))
  563.   ;; Make sure that we're in the correct positions to avoid hassle.
  564.   (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-windows)
  565.   (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily)
  566.   (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-windows)
  567.   (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily t))
  568.  
  569. ;; Functions for fontification:
  570.  
  571. (defun lazy-lock-fontify-window ()
  572.   ;; Fontify the visible part of the buffer where necessary.
  573.   (let ((ws (if lazy-lock-hide-invisible
  574.         (save-excursion
  575.           (end-of-line) (forward-line (- (window-height))) (point))
  576.           (min (max (window-start) (point-min)) (point-max))))
  577.     (we (if lazy-lock-hide-invisible
  578.         (save-excursion
  579.           (end-of-line) (forward-line (window-height)) (point))
  580.           (min (max (1- (window-end)) (point-min)) (point-max)))))
  581.     (if (or (/= ws lazy-lock-cache-start) (/= we lazy-lock-cache-end))
  582.     ;; Find where we haven't `fontified' before.
  583.     (let* ((start (or (text-property-not-all ws we 'fontified t) ws))
  584.            (end (or (text-property-any start we 'fontified t) we))
  585.            (modified (buffer-modified-p)) (inhibit-read-only t)
  586.            ;; We do the following to prevent: undo list addition; region
  587.            ;; highlight disappearance; supersession/locking checks.
  588.            (buffer-undo-list t) deactivate-mark buffer-file-name)
  589.       (while (< start end)
  590.         ;; Fontify and flag the region as `fontified'.
  591.         (font-lock-after-change-function start end 0)
  592.         (put-text-property start end 'fontified t)
  593.         ;; Find the next region.
  594.         (setq start (or (text-property-not-all ws we 'fontified t) ws)
  595.           end (or (text-property-any start we 'fontified t) we)))
  596.       (setq lazy-lock-cache-start ws lazy-lock-cache-end we)
  597.       (or modified (set-buffer-modified-p nil))))))
  598.  
  599. (defun lazy-lock-fontify-walk-windows ()
  600.   ;; Fontify windows in all required by walking through them.
  601.   (save-excursion
  602.     (save-selected-window
  603.       (condition-case nil
  604.       (walk-windows
  605.        (function (lambda (window)
  606.                (select-window window)
  607.                (if lazy-lock-mode (lazy-lock-fontify-window))))
  608.        'no-minibuf (eq lazy-lock-walk-windows 'all-frames))
  609.     (wrong-type-argument
  610.      ;; Looks like the Emacs 19.28 Garbage Collection bug has hit town.
  611.      ;; Completely remove all text properties and restart lazy-lock.
  612.      (set-text-properties (point-min) (point-max) nil)
  613.      (turn-on-lazy-lock)
  614.      (lazy-lock-fontify-window)
  615.      (message "Fontifying window... done.  (Restarted in %s)"
  616.           (buffer-name)))))))
  617.  
  618. (defun lazy-lock-fontify-stealthily ()
  619.   ;; Fontify an invisible part of the buffer where necessary.
  620.   (save-excursion
  621.     ;; Move to the end in case the character to the left is not `fontified'.
  622.     (end-of-line)
  623.     ;; Find where the next and previous regions not `fontified' begin and end.
  624.     (let ((next (text-property-not-all (point) (point-max) 'fontified t))
  625.       (prev (let ((p (previous-single-property-change (point) 'fontified)))
  626.           (and p (> p (point-min)) p)))
  627.       (modified (buffer-modified-p)) (inhibit-read-only t)
  628.       (buffer-undo-list t) deactivate-mark buffer-file-name start end)
  629.       (cond ((and (null next) (null prev))
  630.          ;; Nothing has been `fontified' yet.
  631.          (beginning-of-line 1) (setq start (point))
  632.          (forward-line (or lazy-lock-stealth-lines (window-height)))
  633.          (setq end (point)))
  634.         ((or (null prev)
  635.          (and next (> (- (point) prev) (- next (point)))))
  636.          ;; The next region is the nearest not `fontified'.
  637.          (goto-char next) (beginning-of-line 1) (setq start (point))
  638.          (forward-line (or lazy-lock-stealth-lines (window-height)))
  639.          ;; Maybe the region is already partially `fontified'.
  640.          (setq end (or (text-property-any next (point) 'fontified t)
  641.                (point))))
  642.         (t
  643.          ;; The previous region is the nearest not `fontified'.
  644.          (goto-char prev) (forward-line 1) (setq end (point))
  645.          (forward-line (- (or lazy-lock-stealth-lines (window-height))))
  646.          ;; Maybe the region is already partially `fontified'.
  647.          (setq start
  648.           (or (previous-single-property-change prev 'fontified nil (point))
  649.           (point)))))
  650.       ;; Fontify and flag the region as `fontified'.
  651.       (font-lock-after-change-function start end 0)
  652.       (put-text-property start end 'fontified t)
  653.       (or modified (set-buffer-modified-p nil)))))
  654.  
  655. (defun lazy-lock-fontify-walk-stealthily ()
  656.   ;; Fontify regions in all required buffers while there is no input.
  657.   (let ((buffers (buffer-list)) (continue t) fontified message-log-max)
  658.     (save-excursion
  659.       (while (and buffers continue)
  660.     (set-buffer (car buffers))
  661.     (if (and lazy-lock-mode (lazy-lock-unfontified-p))
  662.         ;; Fontify regions in this buffer while there is no input.
  663.         (let ((bufname (buffer-name)))
  664.           (if (and font-lock-verbose (not fontified))
  665.           (message "Fontifying stealthily..."))
  666.           ;; We `save-restriction' and `widen' around everything as
  667.           ;; `lazy-lock-fontify-stealthily' doesn't and we `sit-for'.
  668.           (save-restriction (widen) (lazy-lock-fontify-stealthily))
  669.           (while (and (lazy-lock-unfontified-p)
  670.               (setq continue (lazy-lock-sit-for
  671.                       lazy-lock-stealth-nice)))
  672.         (if font-lock-verbose
  673.             (message "Fontifying stealthily... %2d%% of %s"
  674.                  (lazy-lock-percent-fontified) bufname))
  675.         (save-restriction (widen) (lazy-lock-fontify-stealthily)))
  676.           ;; Note that fontification occurred.
  677.           (setq fontified t)))
  678.     (setq buffers (cdr buffers))))
  679.     (if (and font-lock-verbose fontified)
  680.     (message "Fontifying stealthily... %s." (if continue "done" "quit")))))
  681.  
  682. (defun lazy-lock-unfontified-p ()
  683.   ;; Return non-nil if there is anywhere still to be `fontified'.
  684.   (save-restriction
  685.     (widen)
  686.     (text-property-not-all (point-min) (point-max) 'fontified t)))
  687.  
  688. (defun lazy-lock-percent-fontified ()
  689.   ;; Return the percentage (of characters) of the buffer that are `fontified'.
  690.   (save-restriction
  691.     (widen)
  692.     (let ((size 0) (start (point-min)) (max (point-max)) end)
  693.       (while (setq start (text-property-any start max 'fontified t))
  694.     (setq end (or (text-property-not-all start max 'fontified t) max)
  695.           size (+ size (- end start))
  696.           start end))
  697.       ;; Saying "99% done" is probably better than "100% done" when it isn't.
  698.       (truncate (/ (* size 100.0) (buffer-size))))))
  699.  
  700. (defun lazy-lock-colour-invisible ()
  701.   ;; Fontify the current buffer in `lazy-lock-invisible-face'.
  702.   (save-restriction
  703.     (widen)
  704.     (let ((face 'lazy-lock-invisible-face)
  705.       (fore (if (stringp lazy-lock-invisible-foreground)
  706.             lazy-lock-invisible-foreground
  707.           (cdr (assq 'background-color (frame-parameters)))))
  708.       (modified (buffer-modified-p)) (inhibit-read-only t)
  709.       (buffer-undo-list t) deactivate-mark buffer-file-name)
  710.       (make-face face)
  711.       (or (equal (face-foreground face) fore) (set-face-foreground face fore))
  712.       (put-text-property (point-min) (point-max) 'face face)
  713.       (put-text-property (point-min) (point-max) 'fontified nil)
  714.       (or modified (set-buffer-modified-p nil)))))
  715.  
  716. ;; Functions for Emacs:
  717.  
  718. ;; This fix is for a number of bugs in the function in Emacs 19.28.
  719. (if (and (not lazy-lock-running-xemacs-p) (< emacs-minor-version 29))
  720.     (defun font-lock-fontify-region (start end &optional loudly)
  721.       "Put proper face on each string and comment between START and END."
  722.       (save-excursion
  723.     (save-restriction
  724.       (widen)
  725.       (goto-char start)
  726.       (beginning-of-line)
  727.       (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
  728.       (let ((inhibit-read-only t) (buffer-undo-list t) (buffer-file-name)
  729.         (modified (buffer-modified-p))
  730.         (old-syntax (syntax-table))
  731.         (synstart (if comment-start-skip
  732.                   (concat "\\s\"\\|" comment-start-skip)
  733.                 "\\s\""))
  734.         (comstart (if comment-start-skip
  735.                   (concat "\\s<\\|" comment-start-skip)
  736.                 "\\s<"))
  737.         (startline (point))
  738.         state prev prevstate)
  739.         (unwind-protect
  740.         (progn
  741.           (if font-lock-syntax-table
  742.               (set-syntax-table font-lock-syntax-table))
  743.           ;; Find the state at the line-beginning before START.
  744.           (if (eq startline font-lock-cache-position)
  745.               (setq state font-lock-cache-state)
  746.             ;; Find outermost containing sexp.
  747.             (beginning-of-defun)
  748.             ;; Find the state at STARTLINE.
  749.             (while (< (point) startline)
  750.               (setq state (parse-partial-sexp (point) startline 0)))
  751.             (setq font-lock-cache-state state
  752.               font-lock-cache-position (point)))
  753.           ;; Now find the state precisely at START.
  754.           (setq state (parse-partial-sexp (point) start nil nil state))
  755.           ;; If the region starts inside a string, show the extent of it.
  756.           (if (nth 3 state)
  757.               (let ((beg (point)))
  758.             (while (and (re-search-forward "\\s\"" end 'move)
  759.                     (nth 3 (parse-partial-sexp beg (point) nil nil
  760.                                    state))))
  761.             (put-text-property beg (point) 'face font-lock-string-face)
  762.             (setq state (parse-partial-sexp beg (point)
  763.                             nil nil state))))
  764.           ;; Likewise for a comment.
  765.           (if (or (nth 4 state) (nth 7 state))
  766.               (let ((beg (point)))
  767.             (save-restriction
  768.               (narrow-to-region (point-min) end)
  769.               (condition-case nil
  770.                   (progn
  771.                 (re-search-backward comstart (point-min) 'move)
  772.                 (forward-comment 1)
  773.                 ;; forward-comment skips all whitespace,
  774.                 ;; so go back to the real end of the comment.
  775.                 (skip-chars-backward " \t"))
  776.                 (error (goto-char end))))
  777.             (put-text-property beg (point) 'face
  778.                        font-lock-comment-face)
  779.             (setq state (parse-partial-sexp beg (point)
  780.                             nil nil state))))
  781.           ;; Find each interesting place between here and END.
  782.           (while (and (< (point) end)
  783.                   (setq prev (point) prevstate state)
  784.                   (re-search-forward synstart end t)
  785.                   (progn
  786.                 ;; Clear out the fonts of what we skip over.
  787.                 (remove-text-properties prev (point) '(face nil))
  788.                 ;; Verify the state at that place
  789.                 ;; so we don't get fooled by \" or \;.
  790.                 (setq state (parse-partial-sexp prev (point)
  791.                                 nil nil state))))
  792.             (let ((here (point)))
  793.               (if (or (nth 4 state) (nth 7 state))
  794.               ;; We found a real comment start.
  795.               (let ((beg (match-beginning 0)))
  796.                 (goto-char beg)
  797.                 (save-restriction
  798.                   (narrow-to-region (point-min) end)
  799.                   (condition-case nil
  800.                   (progn
  801.                     (forward-comment 1)
  802.                     ;; forward-comment skips all whitespace,
  803.                     ;; so go back to the real end of the comment.
  804.                     (skip-chars-backward " \t"))
  805.                 (error (goto-char end))))
  806.                 (put-text-property beg (point) 'face
  807.                            font-lock-comment-face)
  808.                 (setq state (parse-partial-sexp here (point)
  809.                                 nil nil state)))
  810.             (if (nth 3 state)
  811.                 (let ((beg (match-beginning 0)))
  812.                   (while (and (re-search-forward "\\s\"" end 'move)
  813.                       (nth 3 (parse-partial-sexp
  814.                           here (point) nil nil state))))
  815.                   (put-text-property beg (point) 'face
  816.                          font-lock-string-face)
  817.                   (setq state (parse-partial-sexp here (point)
  818.                                   nil nil state))))))
  819.             ;; Make sure PREV is non-nil after the loop
  820.             ;; only if it was set on the very last iteration.
  821.             (setq prev nil)))
  822.           (set-syntax-table old-syntax)
  823.           (and prev
  824.            (remove-text-properties prev end '(face nil)))
  825.           (and (buffer-modified-p)
  826.            (not modified)
  827.            (set-buffer-modified-p nil))))))))
  828.  
  829. ;; Functions for XEmacs:
  830.  
  831. ;; These fix bugs in `text-property-any' and `text-property-not-all'.  They may
  832. ;; not work perfectly in 19.11 and below because `next-single-property-change'
  833. ;; is also broke and not easily fixable in Lisp.
  834. (if (and lazy-lock-running-xemacs-p (< emacs-minor-version 12))
  835.     (progn
  836.       ;; Loop through property changes until found.  This fix includes a work
  837.       ;; around which prevents a bug in `window-start' causing a barf here.
  838.       (defun text-property-any (start end prop value &optional buffer)
  839.     "Check text from START to END to see if PROP is ever `eq' to VALUE.
  840. If so, return the position of the first character whose PROP is `eq'
  841. to VALUE.  Otherwise return nil."
  842.     (let ((start (min start end)) (end (max start end)))
  843.       (while (and start (not (eq (get-text-property start prop buffer) value)))
  844.         (setq start (next-single-property-change start prop buffer end)))
  845.       start))
  846.       ;; No need to loop here; if it's not at START it's at the next change.
  847.       ;; However, `next-single-property-change' sometimes returns LIMIT, or
  848.       ;; `point-max', if no change is found and sometimes returns nil.
  849.       (defun text-property-not-all (start end prop value &optional buffer)
  850.     "Check text from START to END to see if PROP is ever not `eq' to VALUE.
  851. If so, return the position of the first character whose PROP is not
  852. `eq' to VALUE.  Otherwise, return nil."
  853.     (if (not (eq value (get-text-property start prop buffer)))
  854.         start
  855.       (let ((next (next-single-property-change start prop buffer end))
  856.         (end (or end (save-excursion (and buffer (set-buffer buffer))
  857.                          (point-max)))))
  858.         (and next (< next end) next))))))
  859.  
  860. ;; XEmacs 19.11 function `font-lock-any-extents-p' looks for `text-prop' rather
  861. ;; than `face'.  Since `font-lock-unfontify-region' only removes `face', and we
  862. ;; have non-font-lock properties hanging about, `text-prop' never gets removed.
  863. ;; Unfortunately `font-lock-any-extents-p' is inlined so we can't redefine it.
  864. (if (and lazy-lock-running-xemacs-p (< emacs-minor-version 12))
  865.     (add-hook 'font-lock-mode-hook
  866.      (function (lambda ()
  867.     (remove-hook 'after-change-functions 'font-lock-after-change-function)
  868.     (add-hook 'after-change-functions
  869.      (function (lambda (beg end old-len)
  870.         (let ((a-c-beg beg) (a-c-end end))
  871.           (save-excursion
  872.         ;; First set `text-prop' to nil for `font-lock-any-extents-p'.
  873.         (goto-char end) (forward-line 1) (setq end (point))
  874.         (goto-char beg) (beginning-of-line) (setq beg (point))
  875.         (put-text-property beg end 'text-prop nil)
  876.         ;; Then do the real `font-lock-after-change-function'.
  877.         (font-lock-after-change-function a-c-beg a-c-end old-len)
  878.         ;; Now set `fontified' to t to stop `lazy-lock-fontify-window'.
  879.         (put-text-property beg end 'fontified t))))))))))
  880.  
  881. ;; Cope with the differences between Emacs and [LX]Emacs.
  882. (or (fboundp 'frame-parameters)
  883.     (defalias 'frame-parameters 'screen-parameters))
  884.  
  885. ;; Install ourselves:
  886.  
  887. ;; We don't install ourselves on `font-lock-mode-hook' as other packages can be
  888. ;; used with font-lock.el, and lazy-lock.el should be dumpable without forcing
  889. ;; people to get lazy or making it difficult for people to use alternatives.
  890. (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-windows)
  891. (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily t)
  892. (add-hook 'window-setup-hook 'lazy-lock-post-setup-emacs-fontify-windows)
  893. (add-hook 'window-size-change-functions 'lazy-lock-post-resize-fontify-windows)
  894.  
  895. ;; Package-specific.
  896. (add-hook 'ediff-after-setup-control-frame-hooks
  897.       'lazy-lock-post-setup-ediff-control-frame)
  898.  
  899. ;; Might as well uninstall too.  Package-local symbols would be nice...
  900. (and (fboundp 'unintern) (unintern 'lazy-lock-running-xemacs-p))
  901. (and (fboundp 'unintern) (unintern 'lazy-lock-sit-for))
  902.  
  903. ;; Maybe save on the modeline?
  904. ;;(setcdr (assq 'font-lock-mode minor-mode-alist) '(" Lazy"))
  905.  
  906. (or (assq 'lazy-lock-mode minor-mode-alist)
  907.     (setq minor-mode-alist (cons '(lazy-lock-mode " Lazy") minor-mode-alist)))
  908.  
  909. ;; Provide ourselves:
  910.  
  911. (provide 'lazy-lock)
  912.  
  913. ;;; lazy-lock.el ends here
  914.